package com.far.permissions.support;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.far.permisions.rule.base.RuleResultInvoker;
import com.far.permissions.bean.RuleResult;
import com.far.permissions.enums.Symbol;
import com.far.permissions.tools.SqlParserTools;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import org.apache.ibatis.mapping.BoundSql;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class SelectSqlActuator extends BaseSqlActuator {
    public SelectSqlActuator(BoundSql boundSql, RuleResultInvoker ruleResultInvoker) {
        super(boundSql, ruleResultInvoker);
    }

    @Override
    protected void doExecute() throws Exception {
        newSql = remakeSelectSql(originalSql, tablesWithAlias, tablesRuleResult);
        parameterMappings = removeParameterMappings(parameterMappings, tablesRuleResult);
    }

    private String remakeSelectSql(String sql, Map<String, String> tablesWithAlias, List<RuleResult> tablesRuleResult) throws JSQLParserException {
        Select select = SqlParserTools.parseSelectSql(sql);
        PlainSelect selectBody = (PlainSelect) select.getSelectBody();
        Set<String> sqlSegments = new HashSet<>();
        Set<String> inRuleColumns = new HashSet<>();
        tablesRuleResult.forEach((rule) -> {
            String aliasTable = tablesWithAlias.get(rule.getTable());
            String column = aliasTable == null ? rule.getColumn() : aliasTable + StrUtil.DOT + rule.getColumn();
            String segment = SqlParserTools.generateSegment(column, rule.getValue(), Symbol.valueOf(rule.getMode().name()).getExpression());
            sqlSegments.add(segment);
            inRuleColumns.add(column);
        });
        String oldWhere = SqlParserTools.removeColumnsExpression(((PlainSelect) select.getSelectBody()).getWhere(), inRuleColumns).toString();
        String newWhere = CollectionUtil.join(sqlSegments, Symbol.AND.getExpression());
        selectBody.setWhere(SqlParserTools.linkExpressions(oldWhere, newWhere));
        return select.toString();
    }

}
